package com.czk.writer;

import com.czk.utils.FileUtil;
import org.objectweb.asm.AnnotationVisitor;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.FieldVisitor;
import org.objectweb.asm.MethodVisitor;

import static org.objectweb.asm.Opcodes.*;

/**
 * @Author:ChenZhangKun
 * @Date: 2021/9/13 22:29
 */
public class GenerateClass {
    public static void main(String[] args)  {
        // 地址
        String path = "F:\\IdeaProjects\\asm\\target\\classes\\com\\czk\\sample\\Czk.class";
        // 生成的字节码字节流
        byte[] bytes = dump();
        FileUtil.writeBytes(path, bytes);
    }

    private static byte[] dump()  {
        // 创建classWriter
        // ClassWriter.COMPUTE_FRAMES自动计算 max stacks和max locals，也会自动计算stack map frames。
        ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES);
        // 创建类
        cw.visit(V1_8, ACC_PUBLIC, "com/czk/sample/Czk", null, "java/lang/Object", null);
        {
            // ACC_PUBLIC|ACC_STATIC|ACC_FINAL 访问标识符
            // name:字段名称
            // descriptor:字段类型
            // signature:签名
            // value:默认值
            FieldVisitor fieldVisitor = cw.visitField(ACC_PUBLIC | ACC_STATIC | ACC_FINAL, "lover", "Ljava/lang/String;", null, "nzq");
            System.out.println(fieldVisitor.getClass());
            // 加入注解
            AnnotationVisitor annotationVisitor = fieldVisitor.visitAnnotation("Lcom/czk/anotation/Czk;", false);
            // 注解访问完毕
            annotationVisitor.visitEnd();
            fieldVisitor.visitEnd();
        }
        // 创建构造方法
        {
            MethodVisitor methodVisitor = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null);
            // 构造方法代码
            methodVisitor.visitCode();
            // 加载localVariable slot0 this指针的位置
            methodVisitor.visitVarInsn(ALOAD, 0);
            // 执行构造方法
            // INVOKESPECIAL构造方法执行指令
            // owner:Object的类空参构造
            // name:构造方法名称
            // descriptor:构造方法描述
            // isinterface:是否是接口
            methodVisitor.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V", false);
            // 返回语句
            methodVisitor.visitInsn(RETURN);
            methodVisitor.visitMaxs(1,1);
            methodVisitor.visitEnd();
        }

        cw.visitEnd();
        return cw.toByteArray();
    }
}
